package com.laowang.project.system.controller;

import java.io.IOException;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;

import com.github.pagehelper.PageHelper;
import com.laowang.common.exception.CustomException;
import com.laowang.common.utils.DateUtil;
import com.laowang.common.utils.IdWorker;
import com.laowang.common.utils.PayUtil;
import com.laowang.common.utils.SecurityUtils;
import com.laowang.framework.annotation.AccessLimit;
import com.laowang.framework.redis.RedisCache;
import com.laowang.project.pay.config.MyWxPayConfigUtil;
import com.laowang.project.system.domain.*;
import com.laowang.project.system.service.*;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;

import io.swagger.models.auth.In;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.laowang.framework.aspectj.lang.annotation.Log;
import com.laowang.framework.aspectj.lang.enums.BusinessType;

import org.springframework.web.bind.annotation.*;
import com.laowang.framework.web.controller.BaseController;
import com.laowang.framework.web.domain.AjaxResult;
import com.laowang.common.utils.poi.ExcelUtil;
import com.laowang.framework.web.page.TableDataInfo;

import javax.swing.undo.CannotUndoException;

/**
 * 商品购买Controller
 *
 * @author laowang
 * @date 2023-07-21
 */
@Api(tags = "商品购买接口")
@RestController
@RequestMapping("/goodsBuy")
public class MyGoodsBuyController extends BaseController {
    @Autowired
    private MyGoodsBuyService myGoodsBuyService;

    @Autowired
    private MyGoodsService myGoodsService;

    @Autowired
    private WxUserService wxUserService;

    @Autowired
    private UserPointLogService userPointLogService;

    @Autowired
    private UserGoldLogService userGoldLogService;

    @Autowired
    private MyGoodsCatService myGoodsCatService;

    @Autowired
    private RedisCache redisCache;

    @Autowired
    public RedisTemplate redisTemplate;



    @ApiOperation(value = "小程序端 我购买的商品",notes = "")
    @GetMapping("/my")
    public AjaxResult my(Integer pageNum,Integer pageSize) {
        if (pageNum == null && pageSize == null){
            pageNum = 1;
            pageSize = 10;
        }
        PageHelper.startPage(pageNum,pageSize);
        Integer mid = SecurityUtils.getLoginUser().getWxUser().getMid();
        MyGoodsBuy myGoodsBuy = new MyGoodsBuy();
        myGoodsBuy.setUserId(mid);
        myGoodsBuy.setIsPay(1);
        List<MyGoodsBuy> list = myGoodsBuyService.selectMyGoodsBuyList(myGoodsBuy);
        return AjaxResult.success("操作成功",list);
    }

    @ApiOperation(value = "小程序端 兑换商品",notes = "")
    @PostMapping("/exchange")
    @Transactional
    public synchronized AjaxResult exchange(@RequestBody MyGoodsBuy myGoodsBuy1) {
        Integer goodsId = myGoodsBuy1.getGoodsId();
        MyGoods myGoods = myGoodsService.selectMyGoodsById(goodsId);
        if (myGoods == null){
            return AjaxResult.error("商品不存在");
        }
        Integer num = myGoodsBuy1.getNum();
        if (num == null){
            num=1;
        }
        if (myGoods.getStock()< num){
            return AjaxResult.error("商品库存不足");
        }
        Integer mid = SecurityUtils.getLoginUser().getWxUser().getMid();
        WxUser wxUser = wxUserService.selectWxUserById(mid);

        if (myGoods.getVipOnly() !=null &&  myGoods.getVipOnly().equals(1)){
            if (wxUser.getVipLevel() ==null ||  wxUser.getExpireTime().after(new Date())){
                return AjaxResult.error("商品限会员购买");
            }

        }

        if (myGoods.getMonthNum() !=null && myGoods.getMonthNum()>0){
            // 查询当月的购买次数
            int myMonthNum = myGoodsBuyService.getMonthNum(mid,goodsId);
            if (myMonthNum >= myGoods.getMonthNum()){
                return AjaxResult.error("本月购买此商品已达限购数量");
            }
        }

        if (myGoods.getYearNum() !=null && myGoods.getYearNum()>0){
            // 查询年的购买次数
            int myYearNum = myGoodsBuyService.getYearNum(mid,goodsId);
            if (myYearNum >= myGoods.getYearNum()){
                return AjaxResult.error("本年购买此商品已达限购数量");
            }
        }



        Integer isCombo = myGoods.getIsCombo();
        MyGoodsBuy myGoodsBuy =new MyGoodsBuy();
        if (isCombo.equals(0)){
            myGoodsBuy.setIsCombo(0);
            //积分
            Integer points = wxUser.getPoints();
            BigDecimal price = myGoods.getPrice();
            if (points< price.intValue()){
                return AjaxResult.error("积分不足");
            }
            //积分日志
            UserPointLog userPointLog = new UserPointLog();
            userPointLog.setRemark("兑换商品");
            userPointLog.setOldPoint(points);
            userPointLog.setChangePoint(price.negate().intValue());
            userPointLog.setNewPoint(points - price.intValue());
            userPointLog.setUserId(mid);
            userPointLog.setType(5);//兑换
            userPointLog.setCreated(new Date());
            userPointLogService.insertUserPointLog(userPointLog);
            wxUser.setPoints(points - price.intValue());
            wxUserService.updateWxUser(wxUser);

            myGoodsBuy1.setIsPay(1);//已支付

            Integer freezeStock = myGoods.getFreezeStock();//已售数量
            freezeStock += num;
            Integer stock = myGoods.getStock();
            stock -= num;
            myGoods.setFreezeStock(freezeStock);
            myGoods.setStock(stock);

        }else if (isCombo.equals(1)){
            //金币
            myGoodsBuy.setIsCombo(1);
            Integer goldCoin = wxUser.getGoldCoin();//金币
            BigDecimal price = myGoods.getPrice();
            if (goldCoin< price.intValue()){
                return AjaxResult.error("金币不足");
            }
            //金币日志
            UserGoldLog userGoldLog = new UserGoldLog();
            userGoldLog.setRemark("兑换商品");
            userGoldLog.setOldBalance(new BigDecimal(goldCoin) );
            userGoldLog.setChangeBalance(price.negate());
            userGoldLog.setNewBalance(new BigDecimal( goldCoin - price.intValue()));
            userGoldLog.setUserId(mid);
            userGoldLog.setType(7);//兑换
            userGoldLog.setCreated(new Date());
            userGoldLogService.insertUserGoldLog(userGoldLog);

            wxUser.setGoldCoin(goldCoin - price.intValue());
            wxUserService.updateWxUser(wxUser);

            myGoodsBuy1.setIsPay(1);//已支付

            Integer freezeStock = myGoods.getFreezeStock();//已售数量
            freezeStock += num;
            Integer stock = myGoods.getStock();
            stock -= num;
            myGoods.setFreezeStock(freezeStock);
            myGoods.setStock(stock);

        }else if (isCombo.equals(2)){
            myGoodsBuy.setIsCombo(2);
            //金币与积分
            Integer goldCoin = wxUser.getGoldCoin();//金币
            Integer points = wxUser.getPoints();//积分
            Integer jifen = myGoods.getJifen();
            Integer jinbi = myGoods.getJinbi();
            if (points < jifen){
                return AjaxResult.error("积分不足");
            }
            if (goldCoin < jinbi){
                return AjaxResult.error("金币不足");
            }

            //积分日志
            UserPointLog userPointLog = new UserPointLog();
            userPointLog.setRemark("兑换商品");
            userPointLog.setOldPoint(points);
            userPointLog.setChangePoint(jifen);
            userPointLog.setNewPoint(points - jifen);
            userPointLog.setUserId(mid);
            userPointLog.setType(5);//兑换
            userPointLog.setCreated(new Date());
            userPointLogService.insertUserPointLog(userPointLog);

            //金币日志
            UserGoldLog userGoldLog = new UserGoldLog();
            userGoldLog.setRemark("兑换商品");
            userGoldLog.setOldBalance(new BigDecimal(goldCoin) );
            userGoldLog.setChangeBalance(new BigDecimal(jinbi).negate());
            userGoldLog.setNewBalance(new BigDecimal( goldCoin - jinbi));
            userGoldLog.setUserId(mid);
            userGoldLog.setType(7);//兑换
            userGoldLog.setCreated(new Date());
            userGoldLogService.insertUserGoldLog(userGoldLog);

            wxUser.setGoldCoin(goldCoin - jinbi);
            wxUser.setPoints(points - jifen);
            wxUserService.updateWxUser(wxUser);

            myGoodsBuy1.setIsPay(1);//已支付

            Integer freezeStock = myGoods.getFreezeStock();//已售数量
            freezeStock += num;
            Integer stock = myGoods.getStock();
            stock -= num;
            myGoods.setFreezeStock(freezeStock);
            myGoods.setStock(stock);

        }else if (isCombo.equals(3)){

            myGoodsBuy1.setIsPay(0);//已支付
        }

        List<MyGoodsCat> myGoodsCats = myGoodsCatService.selectMyGoodsCatList(null);
        for (MyGoodsCat myGoodsCat : myGoodsCats) {
            if (myGoodsCat.getId().equals(myGoods.getGoodsCatId())) {
                myGoodsBuy.setCat(myGoodsCat.getName());
            }
        }
        myGoodsBuy1.setUserId(mid);
        //myGoodsBuy.setCat("");
        myGoodsBuy1.setCtime(new Date());
        myGoodsBuy1.setImg(myGoods.getImageId());//商品图
        myGoodsBuy1.setGoodsName(myGoods.getName());
        myGoodsBuy1.setGoodsId(goodsId);
        myGoodsBuy1.setPrice(myGoods.getPrice());
        myGoodsBuy1.setStatus(0);//待发货
        //myGoodsBuy1.setIsPay(1);//已支付
        myGoodsBuyService.insertMyGoodsBuy(myGoodsBuy1);


        myGoodsService.updateMyGoods(myGoods);
        return AjaxResult.success("操作成功");
    }


    @ApiOperation(value = "小程序端 兑换商品1",notes = "")
    @PostMapping("/exchange1")
    public AjaxResult exchange1(MyGoodsBuy myGoodsBuy1) {

        Object o =  myGoodsBuyService.exchange1(myGoodsBuy1);

        return AjaxResult.success("操作成功",o);
    }

    @ApiOperation(value = "小程序端 添加购物车",notes = "")
    @PostMapping("/addOrder")
    public AjaxResult addOrder(@RequestBody MyGoodsBuy myGoodsBuy1) {

        Integer mid = SecurityUtils.getLoginUser().getWxUser().getMid();
        WxUser wxUser = wxUserService.selectWxUserById(mid);

        Integer goodsId = myGoodsBuy1.getGoodsId();
        if (goodsId == null){
            return AjaxResult.error("商品参数不能为空");
        }

        MyGoods myGoods = myGoodsService.selectMyGoodsById(goodsId);

        if (myGoods.getVipOnly() !=null &&  myGoods.getVipOnly().equals(1)){
            if (wxUser.getVipLevel() ==null ||  wxUser.getExpireTime().before(new Date())){
                return AjaxResult.error("商品限会员购买");
            }
        }

        if (myGoods.getMonthNum() !=null && myGoods.getMonthNum()>0){
            // 查询当月的购买次数
            int myMonthNum = myGoodsBuyService.getMonthNum(mid,goodsId);
            if (myMonthNum >= myGoods.getMonthNum()){
                return AjaxResult.error("本月购买此商品已达限购数量");
            }
        }

        if (myGoods.getYearNum() !=null && myGoods.getYearNum()>0){
            // 查询年的购买次数
            int myYearNum = myGoodsBuyService.getYearNum(mid,goodsId);
            if (myYearNum >= myGoods.getYearNum()){
                return AjaxResult.error("本年购买此商品已达限购数量");
            }
        }


        myGoodsBuy1.setIsPay(0);
        myGoodsBuy1.setIsCombo(3);
        myGoodsBuy1.setCtime(new Date());
        myGoodsBuy1.setUserId(SecurityUtils.getLoginUser().getWxUser().getMid());
        myGoodsBuyService.insertMyGoodsBuy(myGoodsBuy1);

        return AjaxResult.success("操作成功",myGoodsBuy1.getId());
    }

    //用令牌桶
    @AccessLimit(perSecond = 5, timeOut = 5 ) // 一秒钟放5个令牌  等待超时时间5秒
    @ApiOperation(value = "小程序端 预添加秒杀商品",notes = "")
    @PostMapping("/addSkill")
    public AjaxResult addSkill(MyGoodsBuy myGoodsBuy1) {
        Integer goodsId = myGoodsBuy1.getGoodsId();
        Integer mid = SecurityUtils.getLoginUser().getWxUser().getMid();

        /*//记录用户排队的次数    第一个是key 第二个是每次自增的值
        Long userQueueOrder = redisTemplate.boundHashOps("UserQueueOrder").increment(mid, 1);
        if(userQueueOrder > 1L){
            return AjaxResult.error("已经抢过该商品");
        }*/

        if (goodsId == null) {
            return AjaxResult.error("商品参数不能为空");
        }
        //回调的时候在去更新这里的库存
        MyGoods myGoods = redisCache.getCacheObject("goods:" + goodsId);
        if (myGoods == null){
            synchronized (this){
                myGoods = myGoodsService.selectMyGoodsById(goodsId);
                if (myGoods == null) return AjaxResult.error("没有该抢购商品");
                Integer stock = myGoods.getStock();
                if (stock <= 0) return AjaxResult.error("商品被抢完了!");
                //long l = DateUtil.timeSub12(myGoods.getEndTime(), new Date());
                //l = l + 3600L; // 结束时间加一个小时过期
                //redisCache.setCacheObject("goods:" + goodsId, myGoods, Integer.valueOf(l + ""), TimeUnit.SECONDS);

            }

        }

        WxUser wxUser = wxUserService.selectWxUserById(mid);
        if (myGoods.getVipOnly() != null && myGoods.getVipOnly().equals(1)) {
            if (wxUser.getVipLevel() == null || wxUser.getExpireTime().after(new Date())) {
                return AjaxResult.error("商品限会员购买");
            }
        }

        if (myGoods.getMonthNum() != null && myGoods.getMonthNum() > 0) {
            // 查询当月的购买次数
            int myMonthNum = myGoodsBuyService.getMonthNum(mid, goodsId);
            if (myMonthNum >= myGoods.getMonthNum()) {
                return AjaxResult.error("本月购买此商品已达限购数量");
            }
        }

        if (myGoods.getYearNum() != null && myGoods.getYearNum() > 0) {
            // 查询年的购买次数
            int myYearNum = myGoodsBuyService.getYearNum(mid, goodsId);
            if (myYearNum >= myGoods.getYearNum()) {
                return AjaxResult.error("本年购买此商品已达限购数量");
            }
        }

        // 从缓存中获取数据


        // 缓存非空
        long l = DateUtil.timeSub12(myGoods.getEndTime(), new Date());
        l = l + 3600L; // 结束时间加一个小时过期
        // 是秒杀商品
        if (myGoods.getStartTime().after(new Date()) && myGoods.getEndTime().before(new Date())) {
            Integer stock = myGoods.getStock();
            if (stock <= 0) AjaxResult.error("商品被抢完了!");
            stock--;
            myGoods.setStock(stock);
            Integer freezeStock = myGoods.getFreezeStock();
            freezeStock++;
            myGoods.setFreezeStock(freezeStock);
            redisCache.setCacheObject("goods:" + goodsId, myGoods, Integer.valueOf(l + ""), TimeUnit.SECONDS);

            myGoodsBuy1.setIsPay(0);
            myGoodsBuy1.setIsCombo(3);
            myGoodsBuy1.setCtime(new Date());
            myGoodsBuy1.setUserId(mid);
            myGoodsBuyService.insertMyGoodsBuy(myGoodsBuy1);

        } else {
            return AjaxResult.error("商品的抢购时间已过");
        }


        return AjaxResult.success("操作成功",myGoodsBuy1.getId());
    }

    /**
     * 查询商品购买列表
     */
    @ApiOperation(value = "小程序端 查询商品购买详情",notes = "")
    @GetMapping("/web/one")
    public AjaxResult list(Integer  id) {

        MyGoodsBuy myGoodsBuy = myGoodsBuyService.selectMyGoodsBuyById(id);
        return AjaxResult.success(myGoodsBuy);
    }


    /**
     * 查询商品购买列表
     */
    @ApiOperation(value = "查询商品购买列表",notes = "")
    @PreAuthorize("@ss.hasPermi('my:goodsBuy:list')")
    @GetMapping("/list")
    public TableDataInfo list(MyGoodsBuy myGoodsBuy) {
        startPage();
        List<MyGoodsBuy> list = myGoodsBuyService.selectMyGoodsBuyList(myGoodsBuy);
        return getDataTable(list);
    }

    /**
     * 导出商品购买列表
     */
    @ApiOperation(value = "导出商品购买列表",notes = "")
    @PreAuthorize("@ss.hasPermi('my:goodsBuy:export')")
    @GetMapping("/export")
    public AjaxResult export(MyGoodsBuy myGoodsBuy) {
        List<MyGoodsBuy> list = myGoodsBuyService.selectMyGoodsBuyList(myGoodsBuy);
        ExcelUtil<MyGoodsBuy> util = new ExcelUtil<MyGoodsBuy>(MyGoodsBuy.class);
        return util.exportExcel(list, "goodsBuy");
    }

    /**
     * 获取商品购买详细信息
     */
    @ApiOperation(value = "获取商品购买详细信息",notes = "")
    @PreAuthorize("@ss.hasPermi('my:goodsBuy:query')")
    @GetMapping(value = "/{id}")
    public AjaxResult getInfo(@PathVariable("id") Integer id) {
        return AjaxResult.success(myGoodsBuyService.selectMyGoodsBuyById(id));
    }

    /**
     * 新增商品购买
     */
    @ApiOperation(value = "新增商品购买",notes = "")
    @PreAuthorize("@ss.hasPermi('my:goodsBuy:add')")
    @PostMapping
    public AjaxResult add(@RequestBody MyGoodsBuy myGoodsBuy) {
        return toAjax(myGoodsBuyService.insertMyGoodsBuy(myGoodsBuy));
    }

    /**
     * 修改商品购买
     */
    @ApiOperation(value = "修改商品购买",notes = "")
    @PreAuthorize("@ss.hasPermi('my:goodsBuy:edit')")
    @PutMapping
    public AjaxResult edit(@RequestBody MyGoodsBuy myGoodsBuy) {
        return toAjax(myGoodsBuyService.updateMyGoodsBuy(myGoodsBuy));
    }

    /**
     * 删除商品购买
     */
    @ApiOperation(value = "删除商品购买",notes = "")
    @PreAuthorize("@ss.hasPermi('my:goodsBuy:remove')")
	@DeleteMapping("/{ids}")
    public AjaxResult remove(@PathVariable Integer[] ids) {
        return toAjax(myGoodsBuyService.deleteMyGoodsBuyByIds(ids));
    }
}
